package com.fingard.dsp.bank.directbank.ceb01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.crypto.DigestHelper;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directConfig.NotifySet;
import com.fingard.dsp.bank.directbank.bankInterface.IAcceptNotice;
import com.fingard.dsp.bank.directbank.baofoo01.util.SecurityUtil;
import com.fingard.dsp.bank.directbank.cmb01.CMB01Base;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.dsp.bank.reqrespobj.qryrefund.RetAtsQryRefund;
import com.fingard.dsp.bank.reqrespobj.qryrefund.detail.RetAtsRefundDetail;
import com.fingard.generalobj.NoticeReq;
import com.fingard.generalobj.NoticeResp;
import com.fingard.io.FileHelper;
import com.fingard.net.listener.SocketReceiver;
import com.fingard.text.StringHelper;
import com.fingard.text.UrlHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.apache.commons.lang.SerializationUtils;
import sun.misc.BASE64Decoder;

import java.io.File;
import java.io.PrintStream;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * CEB01-光大银行通知
 *
 * @author fanghh
 * @date 2020.07.02
 * @version 7.1.0
 */
public class CEB01AcceptNotice extends CMB01Base implements IAcceptNotice {
    @Override
    public NoticeResp dealNotice(NoticeReq pNtReq) throws Exception {
        String tmpStrRet = "";

        WriteBankLogLn("回调通知开始保存本地==================");
        NoticeResp resp = new NoticeResp();
        String p_reqs = pNtReq.getReqString();
        WriteBankLogLn("接收到请求：" + pNtReq.getFullString());

        PrintStream ps = null;
        String tmpFileName = FGBiz.DSPHOME_Parent + File.separator + "signnotify";

        java.sql.Connection conn=FGBiz.getLocalDbConn();

        try {
            if (p_reqs.length() == 0) {
                tmpStrRet = "空报文";
                WriteBankLogLn("响应：" + tmpStrRet);
                resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
                return resp;
            }

            //写入文件的字符串
            String key = getBankConfig().getValueAsString("aesKey");
            if (StringHelper.isNullOrEmpty(key)) {
                WriteBankLogLn("请检查config中'aesKey'配置是否为空！");
            }

            byte[] bytes = new BASE64Decoder().decodeBuffer(p_reqs);
            String decryptMsg = SecurityUtil.AesDecrypt(bytes, key);
            decryptMsg = decryptMsg.substring(decryptMsg.indexOf("<"));
            WriteBankLogLn("解密成功，当前银行退票请求明文内容:\r\n" + decryptMsg);
            if (decryptMsg != null) {
                StringBuilder stringBuilder = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(decryptMsg, stringBuilder);
                String payAct = tmpBkReader.getSimpleText("PayAct");
                String saltKey = getBankConfig().getValueAsString("saltKey");
                if (StringHelper.isNullOrEmpty(saltKey)) {
                    WriteBankLogLn("请检查config中'saltKey'配置是否为空！");
                }
                String signData = "RespCode=0&RespInfo=receive success&key=" + saltKey;
                String signature = DigestHelper.cryptoMD5RetHexStr(signData.getBytes(getCharset())).toUpperCase();

                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
                xmlWriter.writeStartElement("ATSYH");
                xmlWriter.writeStartElement("TransResp");
                xmlWriter.writeElementString("BankCode","CEB01");
                xmlWriter.writeStartElement("TransParam");
                xmlWriter.writeStartElement("DetailRecord");
                xmlWriter.writeElementString("RespCode","0");
                xmlWriter.writeElementString("RespInfo","receive success");
                xmlWriter.writeEndElement();
                xmlWriter.writeElementString("Sign",signature);
                xmlWriter.writeEndDocument();

                WriteBankLogLn("返回银行响应明文:\r\n" + xmlWriter.toXmlString());
                WriteBankLogLn("返回银行响应明文字节数:\r\n" + xmlWriter.toXmlString().getBytes("utf-8").length);
                tmpStrRet = SecurityUtil.AesEncrypt(xmlWriter.toXmlString().getBytes("utf-8"), key);

                WriteBankLogLn("返回银行响应密文:\r\n" + tmpStrRet);

                String refundFilePath = tmpFileName + File.separator + payAct + ".txt";
                FileHelper.appendFile(refundFilePath, decryptMsg, "utf-8");

                NotifySet ntfSet = FGBiz.dspCenter.dspConfig.getNotifySet("refundTicket");
                if ("MQ".equals(ntfSet.notifyType)) {
                    XmlTextReader tmpBkReader1 = loadBankRespXmlReader(decryptMsg, stringBuilder);
                    while (tmpBkReader1.read("/ATSYH/TransResp/TransParam/DetailRecord")) {
                        ReqRespHeader tmpHeader = new ReqRespHeader();
                        tmpHeader.bankCode = "CEB01";
                        tmpHeader.transType = "RefundTicket";
                        tmpHeader.transSeqID = Format.DateTime17SSSFormat.format(new Date());
                        RetAtsQryRefund retAts = new RetAtsQryRefund(tmpHeader);
                        retAts.writeStart();

                        RetAtsRefundDetail tmpRetDetail = new RetAtsRefundDetail();
                        tmpRetDetail.payAct = tmpBkReader1.readedXElement.getSingleText("PayAct");

                        String bankNum = tmpBkReader1.readedXElement.getSingleText("AskNum");
                        WriteBankLogLn("当前待匹配银行流水号:" + bankNum);
                        String SELECTSEQ = "SELECT REQSEQID FROM REQSEQIDMAPPING WHERE BANKREQSEQID=?;";
                        Map<String, Object> selMap= JDBCHelper.execQuerySingle(conn,SELECTSEQ,new Object[]{bankNum});
                        if(selMap.size() > 0 ) {
                            tmpRetDetail.askNum = selMap.get("REQSEQID").toString();
                        }else {
                            WriteBankLogLn("当前db数据库表REQSEQIDMAPPING不存在'BANKREQSEQID'字段值为:["+bankNum+"]的记录,请先执行对账单任务后再进行处理.");
                            continue;
                        }
                        tmpRetDetail.recAct = tmpBkReader1.readedXElement.getSingleText("RecAct");
                        tmpRetDetail.recActName = tmpBkReader1.readedXElement.getSingleText("RecActName");
                        tmpRetDetail.amount = tmpBkReader1.readedXElement.getSingleText("Amount");
                        tmpRetDetail.submitTime = tmpBkReader1.readedXElement.getSingleText("SubmitTime");
                        tmpRetDetail.refundTicketDate = Format.DateTimeFormat.format(Format.Date10Format.parse(tmpBkReader1.readedXElement.getSingleText("RefundTicketDate")));
                        tmpRetDetail.refundTicketReason = tmpBkReader1.readedXElement.getSingleText("RefundTicketReason");
                        if (StringHelper.isNullOrEmpty(tmpRetDetail.refundTicketReason)) {
                            tmpRetDetail.refundTicketReason = "退票";
                        } else {
                            tmpRetDetail.refundTicketReason = URLDecoder.decode(tmpRetDetail.refundTicketReason, "utf-8");
                        }
                        retAts.totleNum = "1";
                        retAts.totleAmount = tmpRetDetail.amount;

                        retAts.writeRetDetail(tmpRetDetail);
                        retAts.writeEnd();

                        String notifyReqXML = retAts.getRetAtsString();

                        WriteBankLogLn("MQ通知地址：" + ntfSet.notifyHost);
                        WriteBankLogLn("MQ通知报文：" + notifyReqXML);

                        ConnectionFactory factory = new ConnectionFactory();
                        String[] ipAport = UrlHelper.pickupIpAndPort(ntfSet.notifyHost);
                        factory.setHost(ipAport[0]);
                        factory.setPort(Integer.parseInt(ipAport[1]));
                        factory.setVirtualHost(ntfSet.notifyVirtualHost);
                        factory.setUsername(ntfSet.notifyUsername);
                        factory.setPassword(ntfSet.notifyPassword);

                        Connection connection = factory.newConnection();
                        Channel channel = connection.createChannel();
                        channel.queueDeclare(ntfSet.notifyQueueName, true, false, false, null);

                        HashMap<String, String> mapParams = new HashMap<String, String>();

                        mapParams.put("BankCode", "AllInPay02");
                        mapParams.put("TransType", "RefundTicket");
                        mapParams.put("ReqXml", notifyReqXML);

                        channel.basicPublish("", ntfSet.notifyQueueName, null, SerializationUtils.serialize(mapParams));
                    }
                } else {
                    WriteBankLogLn("未配置notifySet，无需主动通知");
                }
            } else {
                tmpStrRet = "报文格式错误";
                WriteBankLogLn("响应：" + tmpStrRet);
                resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
                return resp;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            WriteBankLogLn(ex);
        } finally {
            if (ps != null) {
                ps.close();
            }
            if (conn != null) {
                conn.close();
            }
        }

        WriteBankLogLn("响应：" + tmpStrRet);
        resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
        return resp;
    }

    @Override
    public void getContentLength(SocketReceiver p_receiver) throws Exception {
    }
}